import { LeftOutlined, RightOutlined } from '@ant-design/icons';
import { List, Card, message } from 'antd';
import { useEffect, useMemo, useRef, useState } from 'react';

import knowService from '@/api/services/knowService';
import { TextArea, Button } from '@/components/eai-design';
import { SvgIcon } from '@/components/icon';
import Markdown from '@/components/markdown';
import NotData from '@/components/NotData';
import { useKnowledgeStore } from '@/store/knowledge';
import { AutoCorrectListType, AutoCorrectTrunksType, OptimizedistType } from '@/types/know/know';

interface DocumentViolationHandlingProps {
  collectionItem: OptimizedistType;
  flag: boolean | undefined;
}

const DocumentViolationHandlingModals = ({
  collectionItem,
  flag,
}: DocumentViolationHandlingProps) => {
  const [ignoredTypos, setIgnoredTypos] = useState<string[]>([]);
  const [sensitiveList, setSensitiveList] = useState<AutoCorrectListType[]>([]);
  const [trunksList, setTrunksList] = useState<AutoCorrectTrunksType[]>();
  const [activeIndex, setActiveIndex] = useState<number>(0);
  const [activeWord, setActiveWord] = useState<string>('');
  const [activeOccurrence, setActiveOccurrence] = useState<number>(0);
  const { setListLength } = useKnowledgeStore();
  const previewRef = useRef<HTMLDivElement>(null);
  const [isReplace, setIsReplace] = useState<boolean>(true);
  const [value, setValue] = useState('');

  useEffect(() => {
    getViolationList();
    setIsReplace(true);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [collectionItem]);
  useEffect(() => {
    if (flag !== undefined) {
      changeAllIgnore();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [flag]);

  useEffect(() => {
    if (sensitiveList && sensitiveList.length > 0) {
      const first = sensitiveList[0];
      const word = getKeyword(first) || '';
      setActiveIndex(0);
      setActiveWord(word);
      setActiveOccurrence(0);
    } else {
      setActiveWord('');
      setActiveOccurrence(0);
      setActiveIndex(0);
    }
    setListLength(sensitiveList?.length || 0);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sensitiveList]);

  const getViolationList = async () => {
    try {
      const res = await knowService.sensitiveDetectionList(
        collectionItem.collectionId,
        collectionItem.appId,
      );
      setSensitiveList(res.all_sensitive_words_with_count);
      setTrunksList(res.trunks);
    } catch (error) {
      console.log(error);
    }
  };

  const getKeyword = (item: any): string =>
    item?.word || item?.correctedText || item?.originalText || '';

  const escapeReg = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  const countMatches = (text: string, word: string): number => {
    if (!word) return 0;
    const reg = new RegExp(escapeReg(word), 'g');
    return (text.match(reg) || []).length;
  };

  const matchMeta = useMemo(() => {
    if (!trunksList || !activeWord) return { offsets: [] as number[], counts: [] as number[] };
    const offsets: number[] = [];
    const counts: number[] = [];
    let acc = 0;
    trunksList.forEach((chunk) => {
      offsets.push(acc);
      const cnt = countMatches(chunk.text, activeWord);
      counts.push(cnt);
      acc += cnt;
    });
    return { offsets, counts };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [trunksList, activeWord]);

  // 生成用于展示的分段列表：若 chunkIndex 不连续，则在中间插入“此段省略”占位
  const displayTrunks = useMemo(() => {
    if (!trunksList || trunksList.length === 0) return [] as any[];
    const sorted = [...trunksList].sort((a, b) => (a.chunkIndex || 0) - (b.chunkIndex || 0));
    const result: any[] = [];
    for (let i = 0; i < sorted.length; i += 1) {
      const current = sorted[i];
      result.push(current);
      const next = sorted[i + 1];
      if (next && (next.chunkIndex || 0) !== (current.chunkIndex || 0) + 1) {
        result.push({ _id: `omitted-${current._id}-${i}`, omitted: true });
      }
    }
    return result;
  }, [trunksList]);

  // 建立 _id 到原始索引的映射，确保高亮计数对齐
  const chunkIdToIndex = useMemo(() => {
    const map: Record<string, number> = {};
    (trunksList || []).forEach((c, idx) => {
      map[c._id] = idx;
    });
    return map;
  }, [trunksList]);

  useEffect(() => {
    const container = previewRef.current;
    if (!container) return;
    const timer = setTimeout(() => {
      const el = container.querySelector('#selected-highlight') as HTMLElement | null;
      if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'center', inline: 'nearest' });
      }
    }, 0);
    // eslint-disable-next-line consistent-return
    return () => clearTimeout(timer);
  }, [activeOccurrence, activeWord, trunksList, sensitiveList]);

  function highlightTypos(
    text: string,
    typoList: Array<{ word?: string; correctedText?: string; originalText?: string }>,
    selectedWord: string,
    localTargetIndex: number | undefined,
  ) {
    const words = (typoList || [])
      .map((t) => getKeyword(t))
      .filter((w): w is string => !!w && !ignoredTypos.includes(w));
    if (!words.length) return text;

    // 宽度无关（全角/半角不敏感）处理辅助
    const toUnicodeEscape = (codePoint: number) =>
      codePoint <= 0xffff
        ? `\\u${codePoint.toString(16).toUpperCase().padStart(4, '0')}`
        : `\\u{${codePoint.toString(16).toUpperCase()}}`;
    const normalizeWidth = (s: string) =>
      Array.from(s)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x3000) return ' ';
          if (cp >= 0xff01 && cp <= 0xff5e) return String.fromCodePoint(cp - 0xfee0);
          return ch;
        })
        .join('');
    const escapeForGroup = (s: string) => escapeReg(s);
    const buildWidthInsensitivePattern = (token: string) =>
      Array.from(token)
        .map((ch) => {
          const cp = ch.codePointAt(0) as number;
          if (cp === 0x20 || cp === 0x3000) {
            return `(?:${toUnicodeEscape(0x20)}|${toUnicodeEscape(0x3000)})`;
          }
          if (cp >= 0x21 && cp <= 0x7e) {
            const fw = cp + 0xfee0;
            return `(?:${escapeForGroup(ch)}|${toUnicodeEscape(fw)})`;
          }
          if (cp >= 0xff01 && cp <= 0xff5e) {
            const hw = cp - 0xfee0;
            return `(?:${toUnicodeEscape(cp)}|${escapeForGroup(String.fromCodePoint(hw))})`;
          }
          return escapeForGroup(ch);
        })
        .join('');

    const unique = Array.from(new Set(words));
    unique.sort((a, b) => b.length - a.length);
    const pattern = new RegExp(unique.map((w) => buildWidthInsensitivePattern(w)).join('|'), 'gu');

    let selectedLocalCounter = 0;
    return text.replace(pattern, (matched) => {
      const isSelectedWord =
        !!selectedWord && normalizeWidth(matched) === normalizeWidth(selectedWord);
      if (isSelectedWord) {
        const current = selectedLocalCounter;
        selectedLocalCounter += 1;
        if (typeof localTargetIndex === 'number' && current === localTargetIndex) {
          return `<span id="selected-highlight" style="background:#FFF1EE;color:#f5222d;font-weight:600;border-bottom:2px solid #FC5353;">${matched}</span>`;
        }
      }
      return `<span style="background:#FFFECA;font-weight:600;border-bottom:2px solid #FFED7B;">${matched}</span>`;
    });
  }

  const changeIgnore = (item: any) => {
    const key = getKeyword(item);
    if (!key) return;
    try {
      knowService.ignoreAutoCorrect({
        collectionId: collectionItem.collectionId,
        appId: collectionItem.appId,
        type: 'sensitive',
        word: [item.word],
        optimizeText: [item.word],
        status: 1,
      });
      setIgnoredTypos((prev) => [...prev, key]);
      setSensitiveList((prev) => prev.filter((w) => getKeyword(w) !== key));
    } catch (error) {
      message.error('忽略失败');
    }
  };

  const changeAllIgnore = () => {
    const allKeys = (sensitiveList || []).map((i) => getKeyword(i)).filter(Boolean) as string[];
    try {
      knowService.ignoreAutoCorrect({
        collectionId: collectionItem.collectionId,
        appId: collectionItem.appId,
        type: 'sensitive',
        word: allKeys,
        optimizeText: allKeys,
        status: 1,
      });
      setIgnoredTypos(allKeys);
      setSensitiveList([]);
    } catch (error) {
      message.error('忽略失败');
    }
  };

  const changeReplace = (item: any) => {
    if (!value) {
      message.info('请输入要替换的内容');
      return;
    }
    setIsReplace(true);
    const original = value;
    const corrected = item?.word || getKeyword(item);
    if (!corrected || !original) return;
    trunksList?.forEach((chunk) => {
      chunk.text = chunk.text.replace(new RegExp(escapeReg(corrected), 'g'), original);
    });
    try {
      knowService.updateOptimize({
        collectionId: collectionItem.collectionId,
        appId: collectionItem.appId,
        type: 'sensitive',
        word: [corrected],
        optimizeText: [original],
        status: 1,
      });
      setIgnoredTypos((prev) => [...prev, original]);
      setSensitiveList((prev) => prev.filter((w) => getKeyword(w) !== corrected));
    } catch (error) {
      message.error('替换失败');
    }
  };

  const handleSelectCard = (item: any, index: number) => {
    const word = getKeyword(item);
    setActiveIndex(index);
    setActiveWord(word);
    setActiveOccurrence(0);
  };

  const handlePrev = (total: number) => {
    if (total <= 1) return;
    setActiveOccurrence((prev) => Math.max(prev - 1, 0));
  };
  const handleNext = (total: number) => {
    if (total <= 1) return;
    setActiveOccurrence((prev) => Math.min(prev + 1, total - 1));
  };

  return (
    <div className="flex h-[600px]">
      {/* 左侧文档预览 */}
      <div className="mr-4 flex w-[50%] flex-1 flex-col rounded-default bg-bg-3">
        <div className="h-full overflow-auto p-4">
          <div className="mb-4 flex items-center ">
            <SvgIcon size={32} icon="document-ic1" className="mr-2" />
            <div className="min-w-0 flex-1 text-@brand-color">
              <div className=" truncate text-base font-semibold text-text-5">
                {collectionItem.fileName}
              </div>
              <div className="mt-1 text-xs text-text-3">
                {collectionItem.size} · {collectionItem.passTime}
              </div>
            </div>
          </div>
          <div
            ref={previewRef}
            className=" hide-scrollbar h-[85%] flex-1 overflow-auto  rounded  text-xs leading-6 text-gray-700"
          >
            {displayTrunks.map((chunk: any) => {
              if (chunk.omitted) {
                return (
                  <div key={chunk._id} className="my-6">
                    <div className="flex items-center text-text-2">
                      <div className="flex-1 border-t border-dashed border-line-2" />
                      <div className="mx-4 text-sm">此段省略</div>
                      <div className="flex-1 border-t border-dashed border-line-2" />
                    </div>
                  </div>
                );
              }
              const origIdx = chunkIdToIndex[chunk._id] ?? 0;
              const startOffset = matchMeta.offsets[origIdx] ?? 0;
              const localIndex = activeOccurrence - startOffset;
              return (
                <div key={chunk._id} className="mb-6">
                  <Markdown
                    source={highlightTypos(
                      chunk.text,
                      sensitiveList || [],
                      activeWord,
                      Number.isFinite(localIndex) ? localIndex : undefined,
                    )}
                  />
                </div>
              );
            })}
          </div>
        </div>
      </div>
      {/* 右侧不合规内容 */}
      <div className="flex w-[40%] flex-col rounded-default bg-bg-3 p-4">
        <div className=" text-sm font-semibold text-text-5">不合规内容</div>
        <div className="mb-4 ">
          <div className="flex items-center justify-between">
            <div className="text-xs text-text-5">
              识别到
              <span className="font-semibold">{sensitiveList?.length}</span>
              项不合规内容
            </div>
            {sensitiveList?.length > 0 && (
              <Button
                className="rounded-default bg-@brand-color px-4 py-1 text-white"
                onClick={changeAllIgnore}
              >
                忽略该问题
              </Button>
            )}
          </div>
        </div>
        <div className="hide-scrollbar flex-1 overflow-auto">
          <List
            dataSource={sensitiveList}
            locale={{ emptyText: <NotData /> }}
            renderItem={(item, index) => {
              const sel = index === activeIndex;
              const total = item?.count || 0;
              return (
                <Card
                  size="small"
                  className={`!mb-4 border ${sel ? '!border-@brand-color' : '!border-line-2'}`}
                  onClick={() => handleSelectCard(item, index)}
                >
                  <div className="mb-2 flex items-center justify-between">
                    <div className="flex items-center">
                      <SvgIcon size={16} icon="document-ic2" className="mr-2" />
                      <span>敏感词</span>
                    </div>
                  </div>
                  <div className="mb-2">
                    文中有{item.count}处存在“{getKeyword(item)}”
                  </div>
                  {!isReplace && sel && (
                    <div className="mb-3">
                      <TextArea
                        placeholder="请输入替换内容"
                        autoSize={{ minRows: 3, maxRows: 5 }}
                        classNames={{
                          textarea: '!border ',
                        }}
                        value={value}
                        onChange={(e) => {
                          setValue(e.target.value);
                        }}
                      />
                    </div>
                  )}
                  <div
                    className={`flex items-center  ${
                      sel && isReplace ? 'justify-between' : ' justify-end'
                    }`}
                  >
                    {sel && isReplace && (
                      <div className="flex gap-2">
                        <Button
                          size="small"
                          type="default"
                          className={`!border !border-line-2 !bg-fill-1 ${
                            total <= 1 || activeOccurrence === 0 ? '!text-text-2' : ''
                          }`}
                          disabled={total <= 1 || activeOccurrence === 0}
                          onClick={(e) => {
                            e.stopPropagation();
                            handlePrev(total);
                          }}
                        >
                          <LeftOutlined />
                        </Button>
                        <div>
                          <span className="text-text-3">
                            {activeOccurrence + 1}/{total}
                          </span>
                        </div>
                        <Button
                          size="small"
                          type="default"
                          className={`!border !border-line-2 !bg-fill-1 ${
                            total <= 1 || activeOccurrence >= total - 1 ? '!text-text-2' : ''
                          }`}
                          disabled={total <= 1 || activeOccurrence >= total - 1}
                          onClick={(e) => {
                            e.stopPropagation();
                            handleNext(total);
                          }}
                        >
                          <RightOutlined />
                        </Button>
                      </div>
                    )}
                    {(isReplace || !sel) && (
                      <div className="flex gap-2">
                        <Button
                          size="small"
                          type="default"
                          className="!border !border-line-2 !bg-fill-1"
                          onClick={(e) => {
                            e.stopPropagation();
                            changeIgnore(item);
                          }}
                        >
                          忽略
                        </Button>
                        <Button
                          className="!border !border-@brand-color !text-@brand-color"
                          size="small"
                          type="default"
                          onClick={(e) => {
                            e.stopPropagation();
                            handleSelectCard(item, index);
                            setIsReplace(false);
                            setValue('');
                          }}
                        >
                          批量替换
                        </Button>
                      </div>
                    )}
                    {!isReplace && sel && (
                      <div className="flex gap-2">
                        <Button
                          size="small"
                          type="default"
                          className="!border !border-line-2 !bg-fill-1"
                          onClick={(e) => {
                            e.stopPropagation();
                            setIsReplace(true);
                          }}
                        >
                          取消
                        </Button>
                        <Button
                          className={`${
                            value.length !== 0
                              ? '!cursor-pointer !border-@brand-color !bg-@brand-color'
                              : '!border-@brand-disabled !cursor-not-allowed !bg-@brand-color-disabled'
                          } !border border-@brand-color  !text-white`}
                          size="small"
                          type="default"
                          onClick={(e) => {
                            e.stopPropagation();
                            changeReplace(item);
                          }}
                        >
                          确定替换
                        </Button>
                      </div>
                    )}
                  </div>
                </Card>
              );
            }}
          />
        </div>
      </div>
    </div>
  );
};

export default DocumentViolationHandlingModals;
